package com.wtwd.campus.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicParameters;
import com.wtwd.campus.annotation.AuditLog;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.common.RespCode;
import com.wtwd.campus.common.RespCodeEntity;
import com.wtwd.campus.common.RespEntity;
import com.wtwd.campus.entity.DeviceInfo;
import com.wtwd.campus.entity.Student;
import com.wtwd.campus.entity.SysUser;
import com.wtwd.campus.entity.VoStudent;
import com.wtwd.campus.model.vo.ResultVO;
import com.wtwd.campus.service.*;
import com.wtwd.campus.utils.AuditLogUtils;
import com.wtwd.campus.utils.CommandSendUtils;
import com.wtwd.campus.utils.GetCurrentSysUserInfoUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author mjy
 * @date 2021/06/16
 * @description
 */
@Api(tags = "学生管理")
@RestController
@RequestMapping("/student")
public class StudentController {
    private static final Logger logger = LoggerFactory.getLogger(StudentController.class);
    @Autowired
    private StudentService studentService;
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Autowired
    public GetCurrentSysUserInfoUtils getCurrentSysUserInfoUtils;
    @Autowired
    private LogService logService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private WXUserStudentPermissionService wxUserStudentPermissionService;
    @Autowired
    private IRMFeignClientNettyService irmFeignClientNettyService;
    @Autowired
    private CommandSendUtils commandSendUtils;


    @ApiOperation(value = "获取学生列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "currentPage", value = "当前页", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "pageSize", value = "页面大小", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "schoolId", value = "学校id", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "gradeId", value = "年级id", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "classesId", value = "班级id", required = true, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "stuName", value = "学生姓名", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "stuPhone", value = "学生手机号", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "parentPhone", value = "家长手机号", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "imei", value = "imei号", required = true, dataTypeClass = String.class),
    })
    /**
     *
     * @param currentPage
     * @param pageSize
     * @param type
     * @param id
     * @param request
     * @return
     */
    @PostMapping("/getStudentList")
    public ResultVO getStudentList(@RequestBody JSONObject jsonObject) {
        logger.info("getStudentList : param " + jsonObject);
        Integer currentPage = jsonObject.getInteger("currentPage");
        Integer pageSize = jsonObject.getInteger("pageSize");
        //学校id,年级id,,班级id必传其一
        if (jsonObject.getInteger("schoolId") == null && jsonObject.getInteger("gradeId") == null && jsonObject.getInteger("classesId") == null) {
            return ResultVO.error(RespCode.PARAMETERIS_MiSSING);
        }
        Page<Student> page = new Page<>(currentPage, pageSize);
        //构建查询map
        HashMap<String, Object> searchMap = new HashMap<>();
        searchMap.put("schoolId", jsonObject.getInteger("schoolId"));
        searchMap.put("gradeId", jsonObject.getInteger("gradeId"));
        searchMap.put("classesId", jsonObject.getInteger("classesId"));
        searchMap.put("stuName", jsonObject.getString("stuName"));
        searchMap.put("stuPhone", jsonObject.getString("stuPhone"));
        searchMap.put("parentPhone", jsonObject.getString("parentPhone"));
        searchMap.put("imei", jsonObject.getString("imei"));
        IPage<Map<String, Object>> data = studentService.getStudentListByCondition(searchMap, page);
        return ResultVO.ok(data);
    }

    /**
     * 添加学生
     * 1.鉴别添加的学生学号在该学校中是否已经存在
     * 2.imei号不需要鉴别，imei号查询出来就是未绑定，并且已经存在的
     *
     * @param voStudent
     * @return
     */
    @PostMapping("/addStudent")
    @AuditLog(operationType = "添加学生", operationContent = "", orgCode = "")
    public RespCodeEntity addStudent(@RequestBody VoStudent voStudent, HttpServletRequest request) {
        String token = request.getHeader(Constants.HEADER_TOKEN_KEY);
        //获取用户的id
        Map<String, Object> msg = redisService.getUserInfoByToken(token);
        String userMsg = (String) msg.get("user");
        JSONObject jsonObject = JSONObject.parseObject(userMsg);
        Integer userId = (Integer) jsonObject.get("userId");
        if (userId == null) {//token过期
            return new RespCodeEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        logger.info("addStudent : param " + voStudent);
        RespCodeEntity checkResult = studentService.checkStudent(voStudent);
        if (checkResult.getCode() != RespCode.SUCCESS.getCode()) {
            return checkResult;
        }
        // 添加学生
        Integer rest = studentService.addStudent(voStudent);
        //修改注释信息
        if (rest > 0) {
            if (voStudent.getDeviceId() != null && voStudent.getStuId() != null) {
                //如果是喜马拉雅的学生则需要下发绑定关系指令
                DeviceInfo device = deviceInfoService.getDeviceInfoByDeviceId(voStudent.getDeviceId());
                sendBindingStatus(Constants.DEVICE_BINDING, voStudent.getStuId(), device, userId);
            }
            Method method = null;
            try {
                method = StudentController.class.getMethod("addStudent", VoStudent.class,HttpServletRequest.class);
                //获取操作的组织id
                String orgCode = logService.getOrgCodeBySchoolId(voStudent.getSchoolId());
                String operationContent = "新增学生".concat(voStudent.getStuName());
                AuditLogUtils.modifyAnnotation(method, operationContent, orgCode);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return new RespCodeEntity(rest > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 修改学生
     * 1.鉴别修改后的学生学号是否已经存在（除开自己本身）
     * 2.鉴别imei号是否修改（如果有修改，解除原有设备绑定重新绑定）
     *
     * @param voStudent
     * @return
     */
    @PutMapping("/updateStudent")
    @AuditLog(operationType = "修改学生信息", operationContent = "", orgCode = "")
    public RespCodeEntity updateStudent(@RequestBody VoStudent voStudent, HttpServletRequest request) {
        logger.info("updateStudent : param " + voStudent.toString());
        String token = request.getHeader(Constants.HEADER_TOKEN_KEY);
        //获取用户的id
        Map<String, Object> msg = redisService.getUserInfoByToken(token);
        String userMsg = (String) msg.get("user");
        JSONObject jsonObject = JSONObject.parseObject(userMsg);
        Integer userId = (Integer) jsonObject.get("userId");
        if (userId == null) {//token过期
            return new RespCodeEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        RespCodeEntity checkResult = studentService.checkUpdateStudent(voStudent);
        if (checkResult.getCode() != RespCode.SUCCESS.getCode()) {
            return checkResult;
        }
        DeviceInfo deviceInfo = deviceInfoService.getDeviceInfoByStudentId(voStudent.getStuId());
        if (voStudent.getDeviceId() != null) {
            if (deviceInfo != null) {//更换设备
                if (!voStudent.getDeviceId().equals(deviceInfo.getDeviceId())) {//如果修改了设备
                    //解绑原来的设备，重新绑定现有设备
                    deviceInfoService.updateBindDevice(deviceInfo.getDeviceId(), voStudent);
                }
            } else {//绑定设备
                deviceInfoService.bindDeviceAndSynchronizationOrg(voStudent);
            }
        } else {
            if (deviceInfo != null) {//原有的设备解绑
                deviceInfoService.unbindStudentByDeviceId(deviceInfo.getDeviceId());
            }//原来没有绑定设备，现在依旧没有绑定,不做任何操作
        }
        //获取修改前学生的信息
        Map<String, Object> oldStudent = studentService.getStudentByStuId(voStudent.getStuId());
        //修改学生数据
        Integer rest = studentService.updateStudent(voStudent);
        //如果是喜马拉雅的设备则进行绑定关系下发
        if (deviceInfo == null && voStudent.getDeviceId() == null) {
            //说明无绑定关系变化，不做操作
        } else {
            if (deviceInfo == null && voStudent.getDeviceId() != null) {
                //说明是新绑定设备
                //查找新设备
                DeviceInfo newDevice = deviceInfoService.getDeviceInfoByStuId(voStudent.getStuId());
                sendBindingStatus(Constants.DEVICE_BINDING, voStudent.getStuId(), newDevice, userId);
            } else {
                if (voStudent.getDeviceId() == null) {
                    //说明是解绑之前的设备
                    sendBindingStatus(Constants.DEVICE_UNBINDING, voStudent.getStuId(), deviceInfo, userId);
                } else {
                    if (voStudent.getDeviceId().equals(deviceInfo.getDeviceId())) {
                        //单纯的修改学生信息
                        sendBindingStatus(Constants.DEVICE_BINDING, voStudent.getStuId(), deviceInfo, userId);
                    } else {
                        //解除原来设备的绑定，绑定新设备
                        sendBindingStatus(Constants.DEVICE_UNBINDING, voStudent.getStuId(), deviceInfo, userId);
                        //查找新设备
                        DeviceInfo newDevice = deviceInfoService.getDeviceInfoByStuId(voStudent.getStuId());
                        sendBindingStatus(Constants.DEVICE_BINDING, voStudent.getStuId(), newDevice, userId);
                    }
                }
            }
        }
        if (rest > 0) {
            //修改注释信息
            Method method = null;
            try {
                method = StudentController.class.getMethod("updateStudent", VoStudent.class, HttpServletRequest.class);
                //获取操作的组织id
                String orgCode = logService.getOrgCodeBySchoolId(voStudent.getSchoolId());
                String operationContent = "";
                String oldName = (String) oldStudent.get("student_name");
                if (!oldName.equals(voStudent.getStuName())) {
                    operationContent = oldName.concat("更改为").concat(voStudent.getStuName());
                } else {
                    operationContent = "修改学生".concat(voStudent.getStuName()).concat("信息");
                }
                AuditLogUtils.modifyAnnotation(method, operationContent, orgCode);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return new RespCodeEntity(rest > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation(value = "学生解绑设备", notes = "")
    @DynamicParameters(name = "unbindDevice", properties = {
            @DynamicParameter(name = "studentId", value = "学生id", dataTypeClass = Integer.class, required = true),
    })
    @PutMapping("/unbindDevice")
    public RespEntity unbindDevice(@RequestBody JSONObject jsonObject) {
        logger.info("unbindDevice :studentId={} ", jsonObject.toJSONString());
        Integer studentId = jsonObject.getInteger("studentId");
        if (studentId == null) {
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        DeviceInfo deviceInfo = deviceInfoService.getDeviceInfoByStudentId(studentId);
        if (deviceInfo == null) {//查看该学生是否绑定设备
            return new RespEntity(RespCode.STUDENT_NOT_BIND_DEVICE);
        }
        //解绑设备
        Integer rest = deviceInfoService.unbindStudentByDeviceId(deviceInfo.getDeviceId());
        return new RespEntity(rest > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 单个删除学生
     * 解绑该学生的设备
     *
     * @param studentId
     * @return
     */
    @DeleteMapping("/deleteStudent/{studentId}")
    @AuditLog(operationType = "删除学生", operationContent = "", orgCode = "")
    public RespCodeEntity deleteStudent(@PathVariable("studentId") Integer studentId) {
        logger.info("deleteStudent : param " + studentId);
        //修改注释信息
        Method method = null;
        try {
            method = StudentController.class.getMethod("deleteStudent", Integer.class);
            //获取操作的组织id
            Map<String, Object> map = logService.getOrgCodeAndStuNameByStuId(studentId);
            if (map != null) {
                String orgCode = (String) map.get("org_code");
                String stuName = (String) map.get("student_name");
                String operationContent = "删除学生".concat(stuName);
                AuditLogUtils.modifyAnnotation(method, operationContent, orgCode);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        Integer rest = studentService.deleteStudentByStudentId(studentId);
        return new RespCodeEntity(rest > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 根据学生id获取绑定了该学生的微信用户
     *
     * @param studentId
     * @return
     */
    @GetMapping("/getWxUser/{studentId}")
    public RespEntity getWxUser(@PathVariable Integer studentId) {
        logger.info("getWxUser : param " + studentId);
        List<Map<String, Object>> wxUserList = studentService.getWxUserByStudentId(studentId);
        return new RespEntity(RespCode.SUCCESS, wxUserList);
    }

    /**
     * 批量导入学生信息
     *
     * @param response
     * @return
     */
    @PostMapping("/importStudentsInfo")
    @AuditLog(operationType = "导入学生信息", operationContent = "", orgCode = "")
    public RespEntity importStudentsInfo(@RequestBody MultipartFile file, HttpServletResponse response, HttpServletRequest request) {
        logger.info("importStudentsInfo");
        SysUser sysUser = getCurrentSysUserInfoUtils.getCurrentSysUserInfo();
        if (sysUser == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        //导入学生
        RespEntity respEntity = studentService.importStudent(file, sysUser, response);
        //修改注释信息
        if (respEntity.getCode() == RespCode.SUCCESS.getCode()) {
            Map<String, Object> data = (Map<String, Object>) respEntity.getData();
            Integer successNum = (Integer) data.get("successNum");
            Method method = null;
            try {
                method = StudentController.class.getMethod("importStudentsInfo", MultipartFile.class, HttpServletResponse.class, HttpServletRequest.class);
                //获取操作的组织id
                String userOrgCode = getUserOrgCode(request);
                String operationContent = "批量导入" + successNum + "条学生信息";
                AuditLogUtils.modifyAnnotation(method, operationContent, userOrgCode);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return respEntity;
    }

    /**
     * 获取用户组织编码
     *
     * @param request
     * @return
     */
    public String getUserOrgCode(HttpServletRequest request) {
        //获取用户的组织编号
        String token = request.getHeader(Constants.HEADER_TOKEN_KEY);
        Map<String, Object> msg = redisService.getUserInfoByToken(token);
        String userMsg = (String) msg.get("user");
        JSONObject jsonObject = JSONObject.parseObject(userMsg);
        String userOrgCode = (String) jsonObject.get("orgCode");
        return userOrgCode;
    }

    /**
     * 解绑微信端的绑定数据
     */
    @PutMapping("/unbindWeChatUser")
    public RespEntity unbindWeChatUser(@RequestBody JSONObject jsonObject) {
        logger.info("unbindWeChatUser" + jsonObject);
        Integer studentId = jsonObject.getInteger("studentId");
        Integer wxUserId = jsonObject.getInteger("wxUserId");
        Integer rest = wxUserStudentPermissionService.unbindWxUserByStudentIdAndWxUserId(studentId, wxUserId);
        return new RespEntity(rest > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 下发绑定关系
     *
     * @param status
     * @param stuId
     */
    public void sendBindingStatus(Integer status, Integer stuId, DeviceInfo deviceInfo, Integer userId) {
        if (deviceInfo != null && !StringUtils.isBlank(deviceInfo.getOrgCode())) {
            logger.info("/下发绑定关系：imei={},stuId={]", deviceInfo.getImei(), stuId.toString());
            //如果原来设备属于喜马拉雅，则进行绑定关系的下发
            if (deviceInfo.getOrgCode().contains("A01A03A05")) {
                boolean isOnline = deviceOnline(deviceInfo.getImei());
                //设备在线则进行发送
                if (status == Constants.DEVICE_BINDING) {
                    //根据学生id获取年级、班级、学生名称、学校名称
                    Map<String, Object> bindingMap = studentService.getStuBindingMessByStuId(deviceInfo.getStudentId());
                    bindingMap.put("imei", deviceInfo.getImei());
                    bindingMap.put("status", status);
                    bindingMap.put("commandNumber", getCurTime());
                    String s = JSONObject.toJSONString(bindingMap);
                    //进行指令下发
                    commandSendUtils.sendBindingStatus(JSONObject.parseObject(s), userId, isOnline, false);
                } else {
                    Map<String, Object> bindingMap = studentService.getStuBindingMessByStuId(deviceInfo.getStudentId());
                    bindingMap.put("imei", deviceInfo.getImei());
                    bindingMap.put("status", status);
                    bindingMap.put("commandNumber", getCurTime());
                    bindingMap.put("schoolName", "");
                    bindingMap.put("classesName", "");
                    bindingMap.put("studentName", "");
                    String s = JSONObject.toJSONString(bindingMap);
                    //进行指令下发
                    commandSendUtils.sendBindingStatus(JSONObject.parseObject(s), userId, isOnline, false);
                }
            }
        }
    }

    /**
     * 判断设备是否在线
     *
     * @param imei 设备imei号
     * @return 设备是否在线
     */
    public boolean deviceOnline(String imei) {
        boolean isOnline = redisService.hasKey(Constants.DEVICE_ONLINE_PREFIX + imei);
        logger.info("设备:【{}】: {}", imei, isOnline ? "在线" : "离线");
        return isOnline;
    }

    /**
     * 获取当前时间的时分秒（HHmmss）
     *
     * @return
     */
    public String getCurTime() {
        Date d = new Date();
        SimpleDateFormat sbf = new SimpleDateFormat("HH:mm:ss");
        String format = sbf.format(d);
        String[] split = format.split(":");
        String time = split[0].concat(split[1]).concat(split[2]);
        return time;
    }
}
